package elijah.eupdater.utils;

import android.content.Context;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import elijah.eupdater.NetApi;
import elijah.eupdater.Progress;
import elijah.eupdater.Eupdater;
import elijah.eupdater.bean.TerminalDevice;
import io.reactivex.Observable;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class HttpUtils {

    public static Observable<Progress> addNewDownload(Context context, TerminalDevice terminalDevice) {
        return Observable.create(observer -> {

            File dir = new File(AppUtils.getUpdateFilePath(context) );
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File localFile = new File(dir, terminalDevice.getUpdateFileName());
            if (localFile.exists()) {
                localFile.delete();
            }
            NetApi.Creator.create(Eupdater.get().getConfig().getHost()).
                    downloadFile(terminalDevice.getUpdateFilePath()).enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    new Thread(){
                        @Override
                        public void run() {
                            try {
                                if (!response.isSuccessful()) {
                                    observer.onError(new Throwable("response is not successful"));
                                    return;
                                }
                                Progress progress = new Progress();

                                ResponseBody body = response.body();
                                long totalSize = body.contentLength();

                                progress.setTotalSize(totalSize);
                                observer.onNext(progress);

                                InputStream inputStream = body.byteStream();
                                OutputStream outputStream = new FileOutputStream(localFile);
                                BufferedSource source = Okio.buffer(Okio.source(inputStream));
                                BufferedSink sink = Okio.buffer(Okio.sink(outputStream));
                                long downloadedSize = 0;
                                int bufferSize = 8 * 1024;
                                long lastSize = 0;
                                long lastTime = System.currentTimeMillis();
                                while (true) {
                                    long readSize = source.read(sink.buffer(), bufferSize);
                                    if (readSize == -1) {
                                        break;
                                    }
                                    sink.emit();
                                    downloadedSize += readSize;
                                    int percent = (int) (downloadedSize * 100 / totalSize);
                                    progress.setProgress(percent)
                                            .setCurSize(downloadedSize);

                                    if ((percent * 100) % 10 == 0) {
                                        progress.setProgress(percent)
                                                .setCurSize(downloadedSize);
                                        observer.onNext(progress);
                                    }

                                    if (System.currentTimeMillis() - lastTime >= 1000) {
                                        progress.setSpeed(downloadedSize - lastSize);
                                        observer.onNext(progress);
                                        lastSize = downloadedSize;
                                        lastTime = System.currentTimeMillis();
                                    }

                                }
                                // 关闭输入输出流
                                source.close();
                                sink.close();
                                observer.onNext(progress.setCurSize(totalSize).setProgress(100));
                                observer.onComplete();
                            } catch (Exception e) {
                                e.printStackTrace();
                                observer.onError(e);
                            }
                        }
                    }.start();

                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    t.printStackTrace();
                    observer.onError(t);
                }
            });
        });
    }

}
